import json
import os
import re
import time

import pdfkit
import requests


# 解析html文件，拿到音频的下载url，然后下载，下载完成之后，给文件进行重命名
def download_mp3(mp3_url, save_url, file_name):
    try:
        if mp3_url is None or save_url is None or file_name is None:
            print('参数错误')
            return None
        # 文件夹不存在，则创建文件夹
        folder = os.path.exists(save_url)
        if not folder:
            os.makedirs(save_url)
        # 读取MP3资源
        res = requests.get(mp3_url, stream=True)
        # 获取文件地址
        file_path = os.path.join(save_url, file_name)
        print('{}开始写入文件：{}'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())), file_path))
        # 打开本地文件夹路径file_path，以二进制流方式写入，保存到本地
        with open(file_path, 'wb') as fd:
            for chunk in res.iter_content():
                fd.write(chunk)
        print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + '   ' + file_name + ' 成功下载！')
    except Exception as e:
        print(e)


'''
下载文章方法
article_url：文章的下载地址
save_path：下载成功后，文件本地保存路径
file_name：文件名
Request URL: https://time.geekbang.org/serv/v1/article
Request Method: POST
封装给浏览器一模一样的请求头
Request Header

payload如下
{"id":40036,"include_neighbors":true,"is_freelyread":true}
其中，id就是文章的id
'''


def download_article(save_path, article_id):
    # 文件夹不存在，则创建文件夹
    folder = os.path.exists(save_path)
    if not folder:
        os.makedirs(save_path)
    cookie_str = "GCID=9c18c5c-12713f0-f6099b4-e618c0a;GCESS=BgkBAQ0BAQcE2guNswsCBgAFBAAAAAADBM3Ij2YGBCR6dCoBCJu_GAAAAAAAAgTNyI9mDAEBCgQAAAAABAQAjScACAED;"
    headers = {
        "Cookie": cookie_str,
        "Referer": "https://time.geekbang.org",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
    }

    data = {"id":article_id,"include_neighbors":True,"is_freelyread":True}
    article_url = 'https://time.geekbang.org/serv/v1/article'
    rsp = requests.post(url=article_url, headers=headers, json=data)
    print("请求接口返回状态码: ", rsp.status_code)
    res = {}
    try:
        if rsp.status_code != 200:
            res = {}
            print(rsp.text)
        res = rsp.json()

    except Exception as e:

        print(e)
    content = res['data']['article_content']
    rstr = r"[\/\\\:\*\?\"\<\>\|\、]"  # '/ \ : * ? " < > |'  将文件名中的特殊字符过滤为下划线
    article_name = re.sub(rstr, "", res['data']['article_title'])
    article_name = article_name.replace("\xa0", "")
    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + '   ' + '开始生成pdf,请稍候...')
    create_pdf_file(save_path, article_name, content)


def create_pdf_file(save_path, article_name, content):
    path_wk = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe'  # wkhtmltopdf安装位置
    config = pdfkit.configuration(wkhtmltopdf=path_wk)
    options = {
        'enable-local-file-access': None,
        'page-size': 'A4',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
        'footer-right': '[page] of [topage]',  # 添加页码
        'minimum-font-size': "33"  # 这是字体大小
    }
    article_path = save_path + '\\\\' + article_name + '.pdf'
    # article_path = save_path + '\\\\' + article_name + '.pdf'
    css_path = r"F:\\python\\jike_time\\myimg.css"
    try:
        pdfkit.from_string(content, article_path, options=options, configuration=config, css=css_path, verbose=True)
    except Exception as e:
        print("下载文章出错")
        print(article_name)
        print(e)
    print('{} 下载完成'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))))


def download_list_articles():
    # "01-Java 业务开发常见错误 100 例", "03-数据结构与算法之美", "04-SQL 必知必会", "05-Redis 核心技术与实战", "06-左耳听风", "07-高并发系统设计40问",
    #                 "08-正则表达式入门", "09-Spring 编程常见错误 50 例", "10-Java 核心技术面试精讲", "11-趣谈 Linux 操作系统", "12-深入浅出计算机组成原理",
    #                 "13-深入拆解 Java 虚拟机",

    # "14-Spring Cloud 微服务项目实战", "15-郭东白的架构课", "16-从 0 开始学架构", "17-MySQL 实战 45 讲",
    #                 "18-消息队列高手课", "20-Kafka 核心技术与实战",

    # "21-Linux 性能优化实战", "22-中间件核心技术与实战","24-RPC 实战与核心原理", "25-深入剖析 Kubernetes", "26-架构实战案例解析",
    # "23-Kafka 核心源码解读",
    # ,"","","","","","","","","","","","","","","","","","",
    article_list = ["42-深入拆解 Tomcat & Jetty","43-深入浅出计算机组成原理","44-高并发系统实战课","45-深入剖析Java新特性","46-操作系统实战 45 讲","47-软件工程之美",
                    "48-代码精进之路","49-业务开发算法 50 讲","50-代码之丑","51-数据分析实战45讲"]
    for article in article_list:
        article_tile = article
        file_name = "源结构体/" + article_tile + ".json"
        with open(file_name, 'r', encoding='utf-8') as f:
            all_article_object = json.loads(f.read())

        # 参考文章https://zhuanlan.zhihu.com/p/502294635

        j = 0
        print("文章总数{}".format(len(all_article_object)))
        save_path_prefix = r'G:\\极客时间\\'
        for i in all_article_object:
            j = j + 1
            rstr = r"[\/\\\:\*\?\"\<\>\|]"  # '/ \ : * ? " < > |'  将文件名中的特殊字符过滤为下划线
            file_name_from_download = re.sub(rstr, "_", i['article_title'])
            print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + '  ' + file_name_from_download)

            attempts = 0
            success = False
            stop_try_times = 500
            while attempts < stop_try_times and not success:

                try:
                    # 如果有音频，那就进行下载  有些文章没有音频，进行下载会拿不到url，然后一直卡主了
                    # if i['include_audio']:
                    #     download_mp3(i['audio_download_url'], save_path_prefix + article_tile + '-音频',
                    #                  file_name_from_download + '.mp3')
                    download_article(save_path_prefix + article_tile + '-文章', i['id'])
                    success = True
                except Exception as e:
                    print(e)
                    attempts += 1
                    time.sleep(102)
                    print("网络错误，重连次数" + str(attempts))
                    if attempts == stop_try_times:
                        break

            time.sleep(10)
        # 下载完成后，把对应的json文件删除
        # os.remove(file_name)



# 下载一个专栏下的文章
# 例如，我这里下载 Java 并发编程实战 这个专栏，需要先把所有的文章id拿到，然后再跟局文章id 下载具体的文章

download_list_articles()

